package com.thz.system.service.matting.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.thz.common.dto.matting.ConversionImageMattingRequestDTO;
import com.thz.common.dto.matting.ConversionImageMattingResponseDTO;
import com.thz.common.entity.ConversionRecord;
import com.thz.common.entity.ConversionRecordImageMatting;
import com.thz.common.enums.ConversionStatus;
import com.thz.common.enums.ConversionType;
import com.thz.common.enums.ErrorCode;
import com.thz.common.exception.BusinessException;
import com.thz.common.utils.FileUtils;
import com.thz.system.config.MattingProperties;
import com.thz.system.service.matting.IAsyncConversionImageMattingService;
import com.thz.system.service.record.IConversionRecordService;
import com.thz.system.mapper.matting.ConversionImageMattingMapper;
import com.thz.system.service.matting.IConversionImageMattingService;
import com.thz.system.service.user.IUserInfoService;
import com.thz.system.utils.ImageMattingUtils;
import com.thz.system.config.CosConfig;
import com.thz.system.utils.cos.CosFileUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.awt.*;
import java.io.File;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;

/**
 * 图片抠图转换服务实现类
 * 
 * @author THZ
 * @date 2025
 */
@Slf4j
@Service
public class ConversionImageMattingServiceImpl 
        extends ServiceImpl<ConversionImageMattingMapper, ConversionRecordImageMatting>
        implements IConversionImageMattingService {
    
    @Autowired
    private ImageMattingUtils imageMattingUtils;
    
    @Autowired
    private IUserInfoService userInfoService;
    
    @Autowired
    private IConversionRecordService conversionRecordService;
    
    @Autowired
    private CosFileUtils cosFileUtils;
    
    @Autowired
    private CosConfig cosConfig;
    
    @Autowired
    private IAsyncConversionImageMattingService asyncConversionImageMattingService;
    
    @Autowired
    private MattingProperties mattingProperties;
    
    @Value("${app.domain:http://localhost:9091}")
    private String serverDomain;
    
    @Override
    public ConversionImageMattingResponseDTO convertImageMatting(
            MultipartFile file, 
            ConversionImageMattingRequestDTO requestDTO, 
            String ipAddress, 
            Long userId) {
        
        // 1. 验证文件
        validateImageFile(file);
        
        // 2. 保存上传的图片文件到COS
        String imageFilePath = cosFileUtils.saveUploadFile(file, null, cosConfig.getUploadPrefix());
        log.info("图片文件已保存到COS: {}", imageFilePath);
        
        // 2.1 下载到本地临时目录进行处理
        String tempPath = System.getProperty("java.io.tmpdir") + "/image_" + System.currentTimeMillis() + "." + FileUtils.getFileExtension(file.getOriginalFilename());
        cosFileUtils.downloadToLocal(imageFilePath, tempPath);
        File imageFile = new File(tempPath);
        log.info("COS文件已下载到临时目录: {}", tempPath);
        
        // 3. 获取或创建用户
        com.thz.common.dto.user.UserInfoDTO userInfoDTO = userInfoService.getOrCreateUser(ipAddress);
        
        // 4. 获取原始图片尺寸
        Dimension originalDimensions;
        try {
            originalDimensions = imageMattingUtils.getImageDimensions(imageFile.getAbsolutePath());
        } catch (Exception e) {
            log.error("获取图片尺寸失败", e);
            throw new BusinessException(ErrorCode.FILE_INVALID, "无法读取图片尺寸");
        }
        
        // 5. 创建转换记录
        ConversionRecordImageMatting record = new ConversionRecordImageMatting();
        record.setOriginalFilename(file.getOriginalFilename());
        record.setOriginalFilePath(imageFilePath);
        record.setOriginalFileSize(file.getSize());
        record.setOriginalWidth(originalDimensions.width);
        record.setOriginalHeight(originalDimensions.height);
        record.setMattingAlgorithm(requestDTO.getAlgorithm() != null ? requestDTO.getAlgorithm() : "REMBG");
        record.setBackgroundColor(requestDTO.getBackgroundColor() != null ? requestDTO.getBackgroundColor() : "transparent");
        record.setConversionStatus(ConversionStatus.PENDING.getCode());
        record.setIpAddress(ipAddress);
        record.setUserId(userId != null ? userId : userInfoDTO.getId());
        record.setCreateTime(LocalDateTime.now());
        record.setUpdateTime(LocalDateTime.now());
        
        this.save(record);
        
        try {
            // 6. 更新状态为转换中
            record.setConversionStatus(ConversionStatus.CONVERTING.getCode());
            this.updateById(record);
            
            // 7. 生成输出文件名和路径（使用系统临时目录）
            String outputFilename = FileUtils.generateUniqueFilename(file.getOriginalFilename())
                    .replaceFirst("\\.[^.]+$", ".png");
            // 使用系统临时目录，无需配置
            String tempDir = System.getProperty("java.io.tmpdir");
            File outputFile = new File(tempDir, outputFilename);
            
            // 8. 执行抠图
            Color bgColor = imageMattingUtils.parseColor(requestDTO.getBackgroundColor());
            // 默认使用 isnet-general-use（平衡速度与精度，且模型大小适中）
            String algorithm = requestDTO.getAlgorithm() != null ? requestDTO.getAlgorithm().toLowerCase() : "isnet-general-use";
            int quality = requestDTO.getQuality() != null ? requestDTO.getQuality() : 95;
            String processingMode = requestDTO.getProcessingMode() != null ? requestDTO.getProcessingMode() : "balanced";
            
            // 在 balanced 平衡模式下自动选择 isnet-general-use，只有明确指定才用自定义
            if ("balanced".equalsIgnoreCase(processingMode)) {
                if (algorithm.trim().isEmpty() || "u2net".equalsIgnoreCase(algorithm) || "u2netp".equalsIgnoreCase(algorithm) || "auto".equalsIgnoreCase(algorithm) || "birefnet-general".equalsIgnoreCase(algorithm)) {
                    String originalAlg = algorithm;
                    algorithm = "isnet-general-use";
                    log.info("平衡模式下选择模型: {} -> {}", originalAlg, algorithm);
                }
            }
            // 大图自动切换到快速模式（阈值可配置）
            try {
                int maxDim = Math.max(originalDimensions.width, originalDimensions.height);
                int threshold = mattingProperties != null ? Math.max(800, mattingProperties.getAutoFastThreshold()) : 1800;
                if (maxDim >= threshold && "balanced".equalsIgnoreCase(processingMode)) {
                    processingMode = "fast";
                }
            } catch (Exception ignore) {}
            
            boolean success = imageMattingUtils.removeBackground(
                    imageFile.getAbsolutePath(),
                    outputFile.getAbsolutePath(),
                    algorithm,
                    bgColor,
                    quality,
                    processingMode
            );
            
            if (!success) {
                throw new BusinessException(ErrorCode.CONVERSION_FAILED, "抠图处理失败");
            }
            
            // 9. 调整尺寸（如果需要）
            if (requestDTO.getWidth() != null || requestDTO.getHeight() != null) {
                int targetWidth = requestDTO.getWidth() != null ? requestDTO.getWidth() : 0;
                int targetHeight = requestDTO.getHeight() != null ? requestDTO.getHeight() : 0;
                
                // 使用临时文件保存调整后的图片
                String tempFilename = "temp_" + outputFilename;
                File tempFile = new File(tempDir, tempFilename);
                
                imageMattingUtils.resizeImage(
                        outputFile.getAbsolutePath(),
                        tempFile.getAbsolutePath(),
                        targetWidth,
                        targetHeight,
                        requestDTO.getKeepAspectRatio(),
                        quality
                );
                
                // 替换原文件
                outputFile.delete();
                tempFile.renameTo(outputFile);
                
                // 🔑 调整尺寸后再次压缩优化
                long sizeBeforeCompress = outputFile.length();
                log.info("调整尺寸后压缩优化，文件={}, 大小={}字节", outputFile.getAbsolutePath(), sizeBeforeCompress);
                imageMattingUtils.compressPngFile(outputFile.getAbsolutePath(), quality);
                long sizeAfterCompress = outputFile.length();
                log.info("压缩优化完成，文件={}, 大小={}字节 (减少{}%)", 
                        outputFile.getAbsolutePath(), sizeAfterCompress,
                        sizeBeforeCompress > 0 ? String.format("%.1f", (1.0 - (double) sizeAfterCompress / sizeBeforeCompress) * 100) : "0");
            }
            
            // 10. 获取输出文件信息（压缩后的大小）
            long outputSize = outputFile.length();
            Dimension outputDimensions = imageMattingUtils.getImageDimensions(outputFile.getAbsolutePath());
            
            // 10.5 上传输出文件到COS
            String outputPath = cosFileUtils.uploadLocalFile(outputFile, cosConfig.getOutputPrefix());
            // 删除本地临时输出文件
            outputFile.delete();
            log.info("输出文件已上传到COS: {}", outputPath);
            
            // 11. 更新转换记录（存储COS URL或本地路径）
            record.setOutputFilename(outputFilename);
            record.setOutputFilePath(outputPath);
            record.setOutputFileSize(outputSize);
            record.setOutputWidth(outputDimensions.width);
            record.setOutputHeight(outputDimensions.height);
            record.setConversionStatus(ConversionStatus.SUCCESS.getCode());
            record.setUpdateTime(LocalDateTime.now());
            
            this.updateById(record);
            
            // 11.1 清理临时图片文件
            if (imageFile.exists()) {
                imageFile.delete();
                log.info("临时图片文件已删除: {}", imageFile.getAbsolutePath());
            }
            
            // 13. 记录到统一转换记录表
            ConversionRecord unifiedRecord = new ConversionRecord();
            unifiedRecord.setUserId(record.getUserId());
            unifiedRecord.setIpAddress(ipAddress);
            unifiedRecord.setConversionType(ConversionType.IMAGE_MATTING.getCode());
            unifiedRecord.setReferenceId(record.getId());
            unifiedRecord.setOriginalFilename(record.getOriginalFilename());
            unifiedRecord.setOutputFilename(outputPath);
            unifiedRecord.setThumbnailFilename(record.getOriginalFilePath());
            unifiedRecord.setOriginalFileSize(record.getOriginalFileSize());
            unifiedRecord.setOutputFileSize(record.getOutputFileSize());
            unifiedRecord.setOutputWidth(record.getOutputWidth());
            unifiedRecord.setOutputHeight(record.getOutputHeight());
            unifiedRecord.setConversionStatus(record.getConversionStatus());
            unifiedRecord.setCreateTime(record.getCreateTime());
            unifiedRecord.setUpdateTime(record.getUpdateTime());
            conversionRecordService.createRecord(unifiedRecord);
            
            // 14. 更新用户转换次数
            userInfoService.incrementConversions(ipAddress);
            
            log.info("图片抠图成功: {} -> {}", imageFile.getName(), outputFilename);
            
            // 15. 返回结果
            return buildResponseDTO(record);
            
        } catch (Exception e) {
            log.error("图片抠图失败", e);
            
            // 清理临时图片文件
            if (imageFile != null && imageFile.exists()) {
                imageFile.delete();
                log.info("失败时清理临时图片文件: {}", imageFile.getAbsolutePath());
            }
            
            // 更新失败状态
            record.setConversionStatus(ConversionStatus.FAILED.getCode());
            record.setErrorMessage(e.getMessage());
            record.setUpdateTime(LocalDateTime.now());
            this.updateById(record);
            
            throw new BusinessException(ErrorCode.CONVERSION_FAILED, e.getMessage(), e);
        }
    }
    
    @Override
    public ConversionImageMattingResponseDTO convertImageMattingAsync(
            MultipartFile file,
            ConversionImageMattingRequestDTO requestDTO,
            String ipAddress,
            Long userId) {
        
        // 1. 验证文件
        validateImageFile(file);
        
        // 2. 保存上传的图片文件到COS
        String imageFilePath = cosFileUtils.saveUploadFile(file, null, cosConfig.getUploadPrefix());
        log.info("[异步抠图] 图片文件已保存到COS: {}", imageFilePath);
        
        // 3. 获取或创建用户
        com.thz.common.dto.user.UserInfoDTO userInfoDTO = userInfoService.getOrCreateUser(ipAddress);
        
        // 4. 下载到本地获取图片尺寸
        String tempPath = System.getProperty("java.io.tmpdir") + "/image_" + System.currentTimeMillis() + "." + 
                FileUtils.getFileExtension(file.getOriginalFilename());
        cosFileUtils.downloadToLocal(imageFilePath, tempPath);
        File tempFile = new File(tempPath);
        
        Dimension originalDimensions;
        try {
            originalDimensions = imageMattingUtils.getImageDimensions(tempFile.getAbsolutePath());
        } catch (Exception e) {
            log.error("获取图片尺寸失败", e);
            throw new BusinessException(ErrorCode.FILE_INVALID, "无法读取图片尺寸");
        } finally {
            // 删除临时文件
            if (tempFile.exists()) {
                tempFile.delete();
            }
        }
        
        // 5. 创建转换记录
        ConversionRecordImageMatting record = new ConversionRecordImageMatting();
        record.setOriginalFilename(file.getOriginalFilename());
        record.setOriginalFilePath(imageFilePath);
        record.setOriginalFileSize(file.getSize());
        record.setOriginalWidth(originalDimensions.width);
        record.setOriginalHeight(originalDimensions.height);
        record.setMattingAlgorithm(requestDTO.getAlgorithm() != null ? requestDTO.getAlgorithm() : "REMBG");
        record.setBackgroundColor(requestDTO.getBackgroundColor() != null ? requestDTO.getBackgroundColor() : "transparent");
        record.setConversionStatus(ConversionStatus.PENDING.getCode());
        record.setIpAddress(ipAddress);
        record.setUserId(userId != null ? userId : userInfoDTO.getId());
        record.setCreateTime(LocalDateTime.now());
        record.setUpdateTime(LocalDateTime.now());
        
        this.save(record);
        
        // 6. 异步执行抠图任务
        asyncConversionImageMattingService.executeImageMattingAsync(
                record.getId(),
                imageFilePath,
                requestDTO,
                ipAddress,
                record.getUserId()
        );
        
        log.info("[异步抠图] 任务已提交，recordId={}", record.getId());
        
        // 7. 立即返回结果（状态为PENDING）
        return buildResponseDTO(record);
    }
    
    @Override
    public ConversionImageMattingResponseDTO getConversionDetail(Long id) {
        ConversionRecordImageMatting record = this.getById(id);
        if (record == null) {
            throw new BusinessException(ErrorCode.CONVERSION_RECORD_NOT_EXISTS);
        }
        return buildResponseDTO(record);
    }
    
    @Override
    public ConversionImageMattingResponseDTO saveManualMattingResult(
            MultipartFile file,
            Long originalId,
            String ipAddress) {
        
        // 1. 验证文件
        validateImageFile(file);
        
        // 2. 获取或创建用户
        com.thz.common.dto.user.UserInfoDTO userInfoDTO = userInfoService.getOrCreateUser(ipAddress);
        
        // 3. 保存上传的手动抠图结果（使用系统临时目录）
        String tempDir = System.getProperty("java.io.tmpdir");
        String outputFilename = FileUtils.generateUniqueFilename(file.getOriginalFilename())
                .replaceFirst("\\.[^.]+$", ".png");
        File outputFile = new File(tempDir, outputFilename);
        
        log.info("准备保存手动抠图结果到: {}", outputFile.getAbsolutePath());
        
        try {
            file.transferTo(outputFile);
            log.info("手动抠图结果已保存: {}", outputFile.getAbsolutePath());
        } catch (Exception e) {
            log.error("保存手动抠图结果失败", e);
            throw new BusinessException(ErrorCode.FILE_SAVE_FAILED);
        }
        
        // 4. 获取图片尺寸
        Dimension outputDimensions;
        try {
            outputDimensions = imageMattingUtils.getImageDimensions(outputFile.getAbsolutePath());
        } catch (Exception e) {
            log.error("获取图片尺寸失败", e);
            throw new BusinessException(ErrorCode.FILE_INVALID, "无法读取图片尺寸");
        }
        
        ConversionRecordImageMatting record;
        
        // 5. 如果有原始记录ID，获取原始记录信息
        if (originalId != null) {
            ConversionRecordImageMatting originalRecord = this.getById(originalId);
            if (originalRecord != null) {
                // 基于原始记录创建新记录
                record = new ConversionRecordImageMatting();
                record.setOriginalFilename(originalRecord.getOriginalFilename());
                record.setOriginalFilePath(originalRecord.getOriginalFilePath());
                record.setOriginalFileSize(originalRecord.getOriginalFileSize());
                record.setOriginalWidth(originalRecord.getOriginalWidth());
                record.setOriginalHeight(originalRecord.getOriginalHeight());
                record.setMattingAlgorithm("手动抠图");
                record.setBackgroundColor("transparent");
            } else {
                // 原始记录不存在，创建新记录
                record = createNewManualRecord(file, outputFile, outputDimensions, userInfoDTO);
            }
        } else {
            // 没有原始ID，创建新记录
            record = createNewManualRecord(file, outputFile, outputDimensions, userInfoDTO);
        }
        
        // 6. 设置输出信息
        record.setOutputFilename(outputFilename);
        record.setOutputFilePath(outputFile.getAbsolutePath());
        record.setOutputFileSize(outputFile.length());
        record.setOutputWidth(outputDimensions.width);
        record.setOutputHeight(outputDimensions.height);
        record.setConversionStatus(ConversionStatus.SUCCESS.getCode());
        record.setIpAddress(ipAddress);
        record.setUserId(userInfoDTO.getId());
        record.setCreateTime(LocalDateTime.now());
        record.setUpdateTime(LocalDateTime.now());
        
        // 7. 保存记录
        this.save(record);
        
        // 8. 记录到统一转换记录表
        ConversionRecord unifiedRecord = new ConversionRecord();
        unifiedRecord.setUserId(record.getUserId());
        unifiedRecord.setIpAddress(ipAddress);
        unifiedRecord.setConversionType(ConversionType.IMAGE_MATTING.getCode());
        unifiedRecord.setReferenceId(record.getId());
            unifiedRecord.setOriginalFilename(record.getOriginalFilename());
            unifiedRecord.setOutputFilename(record.getOutputFilename());
//            unifiedRecord.setThumbnailFilename(record.getOutputFilePath());
            unifiedRecord.setConversionStatus(ConversionStatus.SUCCESS.getCode());
        unifiedRecord.setCreateTime(LocalDateTime.now());
        conversionRecordService.updateRecord(unifiedRecord);
        
        log.info("手动抠图记录已保存: id={}, filename={}", record.getId(), outputFilename);
        
        // 9. 构建并返回响应DTO
        return buildResponseDTO(record);
    }
    
    @Override
    public ConversionImageMattingResponseDTO updateManualMattingResult(
            MultipartFile file,
            Long recordId,
            String ipAddress) {
        
        // 1. 获取原始记录
        ConversionRecordImageMatting record = this.getById(recordId);
        if (record == null) {
            throw new BusinessException(ErrorCode.CONVERSION_RECORD_NOT_EXISTS, "原始记录不存在");
        }
        
        log.info("更新手动抠图记录: recordId={}, originalOutputFile={}", recordId, record.getOutputFilePath());
        
        // 2. 删除旧的输出文件（如果是本地文件）
        if (record.getOutputFilePath() != null) {
            if (cosFileUtils.isCosEnabled() && cosFileUtils.isCosUrl(record.getOutputFilePath())) {
                // 如果是COS文件，删除COS上的文件
                cosFileUtils.deleteFile(record.getOutputFilePath());
                log.info("删除旧的COS输出文件: {}", record.getOutputFilePath());
            } else {
                // 如果是本地文件
                File oldOutputFile = new File(record.getOutputFilePath());
                if (oldOutputFile.exists()) {
                    boolean deleted = oldOutputFile.delete();
                    log.info("删除旧输出文件: {}, 结果: {}", oldOutputFile.getAbsolutePath(), deleted);
                }
            }
        }
        
        // 3. 验证文件
        validateImageFile(file);
        
        // 4. 保存新的输出文件（使用系统临时目录）
        String tempDir = System.getProperty("java.io.tmpdir");
        String outputFilename = FileUtils.generateUniqueFilename(file.getOriginalFilename())
                .replaceFirst("\\.[^.]+$", ".png");
        File outputFile = new File(tempDir, outputFilename);
        
        log.info("准备保存新的手动抠图结果到: {}", outputFile.getAbsolutePath());
        
        try {
            file.transferTo(outputFile);
            log.info("新手动抠图结果已保存: {}", outputFile.getAbsolutePath());
        } catch (Exception e) {
            log.error("保存手动抠图结果失败", e);
            throw new BusinessException(ErrorCode.FILE_SAVE_ERROR, "保存文件失败");
        }
        
        // 4.5 压缩手动抠图结果（减小文件大小）
        long originalFileSize = outputFile.length();
        try {
            int quality = 95; // 手动抠图使用高质量
            log.info("压缩手动抠图结果，文件={}, 原始大小={}字节", outputFile.getAbsolutePath(), originalFileSize);
            imageMattingUtils.compressPngFile(outputFile.getAbsolutePath(), quality);
            long compressedSize = outputFile.length();
            log.info("压缩完成，文件={}, 压缩后大小={}字节 (减少{}%)", 
                    outputFile.getAbsolutePath(), compressedSize,
                    originalFileSize > 0 ? String.format("%.1f", (1.0 - (double) compressedSize / originalFileSize) * 100) : "0");
        } catch (Exception e) {
            log.warn("压缩手动抠图结果失败，继续使用原文件: {}", e.getMessage());
        }
        
        // 5. 获取新图片尺寸
        Dimension outputDimensions;
        try {
            outputDimensions = imageMattingUtils.getImageDimensions(outputFile.getAbsolutePath());
        } catch (Exception e) {
            log.error("获取图片尺寸失败", e);
            throw new BusinessException(ErrorCode.FILE_INVALID, "无法读取图片尺寸");
        }
        
        // 5.5 上传到COS（如果启用）
        String outputFilePath;
        if (cosFileUtils.isCosEnabled()) {
            outputFilePath = cosFileUtils.uploadLocalFile(outputFile, cosConfig.getOutputPrefix());
            // 删除本地临时文件
            outputFile.delete();
            log.info("手动抠图结果已上传到COS: {}", outputFilePath);
        } else {
            outputFilePath = outputFile.getAbsolutePath();
        }
        
        // 6. 更新记录（使用压缩后的大小）
        record.setOutputFilename(outputFilename);
        record.setOutputFilePath(outputFilePath);
        record.setOutputFileSize(outputFile.exists() ? outputFile.length() : originalFileSize);
        record.setOutputWidth(outputDimensions.width);
        record.setOutputHeight(outputDimensions.height);
        record.setMattingAlgorithm("手动抠图");
        record.setUpdateTime(LocalDateTime.now());
        
        this.updateById(record);
        
        // 7. 更新统一转换记录表（重要：历史记录查询依赖此表）
        // 通过 referenceId 查找统一转换记录
        ConversionRecord unifiedRecord = conversionRecordService.findByReferenceId(
                record.getId(), ConversionType.IMAGE_MATTING.getCode());
        
        if (unifiedRecord != null) {
            unifiedRecord.setOutputFilename(outputFilePath);
//            unifiedRecord.setThumbnailFilename(outputFilePath);
            unifiedRecord.setOutputFileSize(file.getSize());
            unifiedRecord.setOutputWidth(outputDimensions.width);
            unifiedRecord.setOutputHeight(outputDimensions.height);
            unifiedRecord.setUpdateTime(LocalDateTime.now());
            conversionRecordService.updateRecord(unifiedRecord);
            log.info("统一转换记录表已更新: referenceId={}, newOutputFile={}", record.getId(), outputFilePath);
        } else {
            // 如果统一记录不存在，创建一个
            unifiedRecord = new ConversionRecord();
            unifiedRecord.setUserId(record.getUserId());
            unifiedRecord.setIpAddress(ipAddress);
            unifiedRecord.setConversionType(ConversionType.IMAGE_MATTING.getCode());
            unifiedRecord.setReferenceId(record.getId());
            unifiedRecord.setOriginalFilename(record.getOriginalFilename());
            unifiedRecord.setOutputFilename(outputFilename);
//            unifiedRecord.setThumbnailFilename(record.getOriginalFilePath());
            unifiedRecord.setOutputFileSize(outputFile.length());
            unifiedRecord.setConversionStatus(ConversionStatus.SUCCESS.getCode());
            unifiedRecord.setCreateTime(LocalDateTime.now());
            unifiedRecord.setUpdateTime(LocalDateTime.now());
            conversionRecordService.createRecord(unifiedRecord);
            log.info("创建新的统一转换记录: referenceId={}, newOutputFile={}", record.getId(), outputFilename);
        }
        
        log.info("手动抠图记录已更新: id={}, newOutputFile={}", recordId, outputFilename);
        
        // 8. 构建并返回响应DTO
        return buildResponseDTO(record);
    }
    
    /**
     * 创建新的手动抠图记录（无原始记录时）
     */
    private ConversionRecordImageMatting createNewManualRecord(
            MultipartFile file,
            File outputFile,
            Dimension outputDimensions,
            com.thz.common.dto.user.UserInfoDTO userInfoDTO) {
        
        ConversionRecordImageMatting record = new ConversionRecordImageMatting();
        record.setOriginalFilename(file.getOriginalFilename());
        record.setOriginalFilePath(outputFile.getAbsolutePath());
        record.setOriginalFileSize(file.getSize());
        record.setOriginalWidth(outputDimensions.width);
        record.setOriginalHeight(outputDimensions.height);
        record.setMattingAlgorithm("手动抠图");
        record.setBackgroundColor("transparent");
        
        return record;
    }
    
    /**
     * 验证图片文件
     */
    private void validateImageFile(MultipartFile file) {
        if (file == null || file.isEmpty()) {
            throw new BusinessException(ErrorCode.FILE_EMPTY);
        }
        
        // 检查文件大小（限制为20MB）
        long maxSize = 20 * 1024 * 1024;
        if (file.getSize() > maxSize) {
            throw new BusinessException(ErrorCode.FILE_TOO_LARGE);
        }
        
        // 检查文件类型
        String originalFilename = file.getOriginalFilename();
        if (originalFilename == null || !isImageFile(originalFilename)) {
            throw new BusinessException(ErrorCode.FILE_FORMAT_ERROR);
        }
    }
    
    /**
     * 判断是否为图片文件
     */
    private boolean isImageFile(String filename) {
        String extension = FileUtils.getFileExtension(filename).toLowerCase();
        return extension.matches("jpg|jpeg|png|webp|bmp|gif");
    }
    
    /**
     * 构建响应DTO
     */
    private ConversionImageMattingResponseDTO buildResponseDTO(ConversionRecordImageMatting record) {
        ConversionImageMattingResponseDTO dto = new ConversionImageMattingResponseDTO();
        BeanUtil.copyProperties(record, dto);
        
        // 构建输出文件URL（用于下载，避免跨域）
        if (record.getOutputFilePath() != null) {
            String outputUrl = record.getOutputFilePath();
            
            // 如果不是完整的URL，先转换为COS URL
            if (!outputUrl.startsWith("http://") && !outputUrl.startsWith("https://")) {
                outputUrl = cosFileUtils.getFileUrl(outputUrl, null);
            }
            
            // 对于COS URL，使用代理URL用于下载（添加download=true参数）
            if (outputUrl.startsWith("http://") || outputUrl.startsWith("https://")) {
                // 构建下载代理URL（带download=true参数，触发下载）
                String downloadProxyUrl = buildProxyUrl(outputUrl, true);
                dto.setDownloadUrl(downloadProxyUrl);
                log.info("构建下载URL (代理): {}", downloadProxyUrl);
            } else {
                // 本地文件（理论上不应该出现，因为都上传到COS了）
                dto.setDownloadUrl(outputUrl);
                log.warn("构建下载URL (本地文件，可能配置错误): {}", outputUrl);
            }
        }
        
        // 构建原始文件URL（用于预览）
        if (record.getOriginalFilePath() != null) {
            String originalUrl = record.getOriginalFilePath();
            
            // 如果不是完整的URL，先转换为COS URL
            if (!originalUrl.startsWith("http://") && !originalUrl.startsWith("https://")) {
                originalUrl = cosFileUtils.getFileUrl(originalUrl, null);
            }
            
            // 对于COS URL，使用代理URL用于预览（不带download参数，用于预览）
            if (originalUrl.startsWith("http://") || originalUrl.startsWith("https://")) {
                // 构建预览代理URL（不带download参数，用于预览）
                String previewProxyUrl = buildProxyUrl(originalUrl, false);
                dto.setOriginalFileUrl(previewProxyUrl);
                log.info("构建原始文件URL (代理预览): {}", previewProxyUrl);
            } else {
                // 本地文件
                dto.setOriginalFileUrl(originalUrl);
                log.warn("构建原始文件URL (本地文件，可能配置错误): {}", originalUrl);
            }
        }
        
        return dto;
    }
    
    /**
     * 构建代理URL
     * 用于避免跨域问题，区分预览和下载
     * 
     * @param cosUrl COS文件URL
     * @param download 是否用于下载（true=下载，false=预览）
     * @return 代理URL
     */
    private String buildProxyUrl(String cosUrl, boolean download) {
        try {
            String encodedUrl = URLEncoder.encode(cosUrl, StandardCharsets.UTF_8);
            String proxyUrl = serverDomain + "/api/files/proxy?url=" + encodedUrl;
            if (download) {
                proxyUrl += "&download=true";
            }
            return proxyUrl;
        } catch (Exception e) {
            log.error("构建代理URL失败: {}", cosUrl, e);
            return cosUrl;
        }
    }
}



